package impl

import (
	"gf-xb-api/cwt/filter/model"
	"gf-xb-api/cwt/filter/parser/group"
	"gf-xb-api/utility/xstr"
	"strconv"

	"github.com/gogf/gf/v2/database/gdb"
)

// GetFilterGroupParser ... 获得分组过滤解析器
func GetFilterGroupParser[T any](key any) (group.IFilterGroupParser[T], error) {
	keyStr, err := xstr.GetKeyStr(key)
	if err != nil {
		return nil, err
	}

	var filterGroupParser group.IFilterGroupParser[T]

	switch *keyStr {
	case strconv.Itoa(model.And), model.AndOperator:
		filterGroupParser = &AndFilterGroupParser[T]{}
	case strconv.Itoa(model.Or), model.OrOperator:
		filterGroupParser = &OrFilterGroupParser[T]{}
	}

	return filterGroupParser, nil
}

// GetConsumerByQueryGroup ... 分析条件组 获得条件组WhereBuilder
func GetConsumerByQueryGroup[T any](group model.FilterGroup[T], m *gdb.Model) (*gdb.WhereBuilder, error) {
	consumer, err := ParseConsumer(group, m)
	if err != nil {
		return nil, err
	}

	return consumer, nil
}

// ParseConsumer ... 解析条件组
func ParseConsumer[T any](group model.FilterGroup[T], m *gdb.Model) (*gdb.WhereBuilder, error) {

	groupParser, err := GetFilterGroupParser[T](group.Operate)
	if err != nil {
		return nil, err
	}

	var rBuilder *gdb.WhereBuilder

	// rules
	rulesLen := len(group.Rules)
	hasRules := rulesLen > 0
	if hasRules {
		for _, rule := range group.Rules {

			ruleWhereBuilder, err := groupParser.ParseWrapperRule(rule, m)
			if err != nil {
				return nil, err
			}

			if rBuilder == nil {
				rBuilder = ruleWhereBuilder
			} else {
				rBuilder = groupParser.MergeQueryWrappers(rBuilder, ruleWhereBuilder)
			}
		}
	}

	// groups
	groups := group.Groups
	groupsLen := len(groups)

	var gBuilder *gdb.WhereBuilder
	hasGroups := groupsLen > 0
	if hasGroups {

		for _, g := range groups {
			groupWhereBuilder, err := GetConsumerByQueryGroup(*g, m)
			if err != nil {
				return nil, err
			}

			if gBuilder == nil {
				gBuilder = groupWhereBuilder
			} else {
				gBuilder = groupParser.MergeQueryWrappers(gBuilder, groupWhereBuilder)
			}
		}
	}

	if hasRules && hasGroups {
		return groupParser.MergeQueryWrappers(rBuilder, gBuilder), nil
	}

	if hasRules {
		return rBuilder, nil
	}

	if hasGroups {
		return gBuilder, nil
	}

	return nil, nil
}
